<?php

namespace App\Http\Controllers\Web\Pay;

use App\ConstDir\ErrorConst;
use App\Http\Controllers\Web\BaseController;
use App\Repository\Models\Orders;
use App\Repository\Models\PaymentOrder;
use App\Repository\Repositories\Interfaces\OrdersRepository;
use App\Repository\Repositories\Interfaces\PaymentOrderRepository;
use App\Services\Pay\CzbankService;
use Illuminate\Http\Request;
use Mockery\Exception;

class CzbankController extends BaseController
{
    protected $payment_order_repo;

    protected $czbank_service;

    public function __construct(PaymentOrderRepository $payment_order_repo, CzbankService $czbank_service)
    {
        $this->payment_order_repo = $payment_order_repo;
        $this->czbank_service = $czbank_service;
    }

    /**
     * 校验订单并生成流水号
     * @param Request $request
     * @param OrdersRepository $orders_repo
     * @return \Illuminate\Support\Collection
     */
    public function checkOrder(Request $request, OrdersRepository $orders_repo)
    {
        $this->validate($request, [
            'order_codes' => 'required', //多个订单号组合，以逗号分割
            'access_key' => 'required',
            'pay_channel' => 'required|in:' . implode(',', array_keys(PaymentOrder::$channel_map)),
        ]);
        $data = $request->all(['order_codes', 'access_key', 'pay_channel']);
        $order_codes_str = urldecode($data['order_codes']);
        $order_codes = explode(',', $order_codes_str);

        $orders = $orders_repo->with(['receivingAccount' => function($sql){
            $sql->orderBy('is_default', 'desc');
        }])->findWhereIn('order_code', $order_codes);

        if (!$orders['data']) {
            return $this->error(ErrorConst::NO_DATA_CODE_MSG, ErrorConst::NO_DATA_CODE);
        }

        $total_order_money = 0;
        $receipt_info_arr = [];
        foreach ($orders['data'] as $order) {
            $total_order_money += $order['order_money'];
            //返回给浙商的收款信息
            $receipt_info_arr[] = [
                'receiptAmount' => number_format($order['order_money'], 2, '.', ''),
                'receiptType' => '1',
                'receiptSerialNo' => array_get($order['receiving_account'], '0.czbank_no'),
            ];
            if ($order['order_status'] != 1 || $order['pay_status'] !== 0) {
                return $this->error(ErrorConst::NO_DATA_CODE_MSG, ErrorConst::NO_DATA_CODE);
            }
        }
        $receipt_info = json_encode($receipt_info_arr);

        //判断所有订单是否属于同一个用户
        $user_ids = array_unique(array_column($orders['data'], 'user_id'));
        if (count($user_ids) != 1) {
            return $this->error(ErrorConst::FAILED_CODE_MSG, ErrorConst::FAILED_CODE);
        }
        $user_id = $user_ids[0];

        if (!$this->czbank_service->checkKey($data['access_key'], $order_codes_str, $total_order_money)) {
            return $this->error(ErrorConst::PAY_VERIFY_FAILED_MSG, ErrorConst::PAY_VERIFY_FAILED_CODE);
        }

        //生成交易流水
        $payment_order_data = [];
        $payment_order_data['user_id'] = $user_id;
        $payment_order_data['channel'] = $data['pay_channel'];
        $payment_order_data['order_codes'] = json_encode($order_codes);
        $payment_order_data['order_money'] = $total_order_money;
        $payment_order_data['pay_money'] = $total_order_money;
        $payment_order_data['paytime'] = date('Y-m-d H:i:s');
        $payment_order_data['payment_type'] = PaymentOrder::PAYMENT_TYPE_PAY;
        $payment_order = $this->payment_order_repo->create($payment_order_data);

        if ($payment_order['data']) {
            $return_access_key = $this->czbank_service->generateKey($order_codes_str, $total_order_money, $receipt_info);
            return $this->success(ErrorConst::SUCCESS_CODE_MSG, ['access_key' => $return_access_key, 'trade_no' => $payment_order['data']['trade_no'], 'receipt_info' => $receipt_info]);
        }

        return $this->error(ErrorConst::FAILED_CODE_MSG, ErrorConst::FAILED_CODE);
    }

    /**
     * 支付完成回调函数
     * @param Request $request
     * @param PaymentOrderRepository $payment_order_repo
     * @param OrdersRepository $orders_repo
     * @return \Illuminate\Support\Collection
     */
    public function notify(Request $request, PaymentOrderRepository $payment_order_repo, OrdersRepository $orders_repo)
    {
        $this->validate($request, [
            'trade_no' => 'required', //流水号
            'access_key' => 'required',
            'pay_status' => 'required|in:' . $this->czbank_service->czbank_unpaid . ',' . $this->czbank_service->czbank_prepaid,
        ]);
        $data = $request->all(['trade_no', 'access_key', 'pay_status']);

        //验签不通过，返回错误
        if (!$this->czbank_service->notifyCheckKey($data['access_key'], $data['trade_no'], $data['pay_status'])) {
            return $this->error(ErrorConst::PAY_VERIFY_FAILED_MSG, ErrorConst::PAY_VERIFY_FAILED_CODE);
        }

        $payment_order_data = $payment_order_repo->whereFirst(['trade_no' => $data['trade_no'], 'pay_status' => PaymentOrder::PAY_STATUS_UNPAID]);
        $payment_order = $payment_order_data['data'];

        \DB::beginTransaction();
        try {
            //浙商暂时无支付时间返回
            $pay_at = date('Y-m-d H:i:s', time());

            //修改支付流水
            $payment_order_repo->paySuccess($data['trade_no'], $pay_at);

            //修改订单状态
            $order_codes = json_decode($payment_order['order_codes']);
            $orders_repo->paySuccess($order_codes, $pay_at, $data['trade_no'], array_get(PaymentOrder::$channel_map, $payment_order['channel']));

            //修改卖家收款列表，暂时无需写入

            \DB::commit();
        } catch (Exception $e) {
            \DB::rollback();
        }

        if (true) {
            return $this->success(ErrorConst::SUCCESS_CODE_MSG, ['access_key' => $this->czbank_service->notifyGenerateKey($data['trade_no'])]);
        } else {
            return $this->error(ErrorConst::FAILED_CODE_MSG, ErrorConst::FAILED_CODE);
        }
    }


}
